using System;
using System.Linq;
using System.Timers;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Framework;
using Kaleida.ServiceMonitor.Model.Email;

namespace Kaleida.ServiceMonitor.Model
{
    public class ScheduledSummaryEmailer : IServiceMonExtension
    {
        private readonly Monitor monitor;
        private readonly NotificationMessageBuilder builder = new NotificationMessageBuilder();
        private string lastSentDatedTime;
        private readonly Timer timeCheckTimer = new Timer(1000){AutoReset = true};
        private readonly OperationStatisticsMap statsSinceLastSummary = new OperationStatisticsMap();

        [CanBeNull]
        private ScriptEmailSender emailSender;

        public ScheduledSummaryEmailer(Monitor monitor)
        {
            this.monitor = monitor;
            timeCheckTimer.Elapsed += (o, e) => CheckTime();
        }

        public void ScriptCompilationComplete(ScriptCompilationCompleteEventArgs args)
        {
            if(args.ScriptCompilation.Succeeded)
            {
                statsSinceLastSummary.Initialise(args.ScriptCompilation.CompiledScript.Operations);
            }
        }

        public void OnStartedMonitoring()
        {
            var compilation = monitor.State.ScriptCompilation;
            if (compilation != null)
            {
                var recipients = compilation.CompiledScript.EmailSummarySchedule.Recipients;
                if (recipients.Any())
                {
                    var scriptName = monitor.Workspace.CurrentScript.Name;
                    {
                        emailSender = new ScriptEmailSender(scriptName, recipients);
                        emailSender.Configure(monitor.Configuration);
                        timeCheckTimer.Start();
                        statsSinceLastSummary.Start();
                    }
                }
            }
        }

        public void OnOperationSuccessful(OperationSuccessfulEventArgs args)
        {
            lock (this)
            {
                statsSinceLastSummary.IncrementSuccessCount(args.Operation, args.Result.RequestDuration);
            }
        }

        public void OnOperationFailed(OperationFailedEventArgs args)
        {
            lock (this)
            {
                statsSinceLastSummary.IncrementFailureCount(args.Operation);
            }
        }

        public void OnErrorsAcknowledged()
        {
        }

        private void CheckTime()
        {
            var compilation = monitor.State.ScriptCompilation;
            if (compilation != null && compilation.Succeeded)
            {
                var schedule = compilation.CompiledScript.EmailSummarySchedule;

                if(schedule.Recipients.Any())
                {
                    lock (this)
                    {
                        var now = DateTime.Now;
                        var currentDatedTime = BuildDatedTime(now);
                        var firstMatch = schedule.Times.FirstOrDefault(i => new ScheduledTime(now.TimeOfDay) == i);

                        if (firstMatch != null && (lastSentDatedTime == null || lastSentDatedTime != currentDatedTime))
                        {
                            var message = builder.BuildSummary(monitor, statsSinceLastSummary);

                            if (message != null && emailSender != null)
                            {
                                emailSender.TrySendEmail(message);
                                lastSentDatedTime = currentDatedTime;
                                statsSinceLastSummary.ResetAll();
                                statsSinceLastSummary.Start();
                            }
                        }
                    }
                }
            }
        }

        private string BuildDatedTime(DateTime dateTime)
        {
            return dateTime.ToString("dd-MMM-yyyy HH:mm");
        }
    }
}